package fr.asip.cps3.exemple.vues;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.apache.log4j.Logger;

import fr.asip.cps3.exemple.controleurs.ApplicationControleur;
import fr.asip.cps3.exemple.controleurs.ApplicationVue;
import fr.asip.cps3.exemple.controleurs.MenuControleur;
import fr.asip.cps3.exemple.modele.Application;
import fr.asip.cps3.exemple.modele.MenuApplication;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionControleur;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionProgrammeExemple;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionVue;
import fr.asip.cps3.exemple.modele.objets.Algo;
import fr.asip.cps3.exemple.modele.objets.Cle;
import fr.asip.cps3.exemple.modele.objets.Objet;
import fr.asip.cps3.exemple.modele.resultats.Resultat;
import fr.asip.cps3.exemple.modele.resultats.ResultatDouble;
import fr.asip.cps3.exemple.modele.resultats.ResultatDoubleInfo;
import fr.asip.cps3.exemple.modele.resultats.ResultatEmpreinteFichier;
import fr.asip.cps3.exemple.modele.resultats.ResultatEmpreinteMessage;
import fr.asip.cps3.exemple.modele.resultats.ResultatInfo;
import fr.asip.cps3.exemple.modele.resultats.ResultatSignatureFichier;
import fr.asip.cps3.exemple.modele.resultats.ResultatSignatureMessage;
import fr.asip.cps3.exemple.modele.resultats.ResultatSpecifique;
import fr.asip.cps3.exemple.modele.resultats.ResultatSpecifiqueInfo;
import fr.asip.cps3.exemple.modele.resultats.ResultatTriple;
import fr.asip.cps3.exemple.modele.resultats.ResultatTripleInfo;
import fr.asip.cps3.exemple.modele.traitements.util.TraitementsUtil;
import fr.asip.cps3.exemple.vues.composants.BarreStatut;
import fr.asip.cps3.exemple.vues.dialogs.SaisieAttributObjet;
import fr.asip.cps3.exemple.vues.dialogs.SaisieCodeNbEssais;
import fr.asip.cps3.exemple.vues.dialogs.SaisieRecyclage;
import fr.asip.cps3.exemple.vues.ecrans.Ecran;
import fr.asip.cps3.exemple.vues.ecrans.EcranUtil;
import fr.asip.cps3.exemple.vues.ecrans.resultats.Sortie;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultat;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatDouble;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatDoubleInfo;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatEmpreinteFichier;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatEmpreinteMessage;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatInfo;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatSignatureFichier;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatSignatureMessage;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatSpecifique;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatSpecifiqueInfo;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatTriple;
import fr.asip.cps3.exemple.vues.ecrans.resultats.SortieResultatTripleInfo;
import fr.asip.cps3.exemple.vues.ecrans.saisie.Saisie1PIN;
import fr.asip.cps3.exemple.vues.ecrans.saisie.Saisie2PIN;
import fr.asip.cps3.exemple.vues.ecrans.saisie.Saisie3PIN;
import fr.asip.cps3.exemple.vues.ecrans.saisie.SaisieFichier;
import fr.asip.cps3.exemple.vues.ecrans.saisie.SaisieFichierSignature;
import fr.asip.cps3.exemple.vues.ecrans.saisie.SaisieFiltreObjet;
import fr.asip.cps3.exemple.vues.ecrans.saisie.SaisieMessage;
import fr.asip.cps3.exemple.vues.ecrans.saisie.SaisieMessageSignature;
import fr.asip.cps3.exemple.vues.ecrans.saisie.SaisieObjet;
import fr.asip.cps3.exemple.vues.ecrans.saisie.SaisieSeed;
import fr.asip.cps3.exemple.vues.menus.ItemMenu;
import fr.asip.cps3.exemple.vues.menus.ItemMenuCheckbox;
import fr.asip.cps3.exemple.vues.menus.Menu;

/**
 * Classe modélisant la fenêtre principale de l'application
 */
public class FenetrePrincipale extends ApplicationVue implements ActionListener {

	/**
	 * Le loggeur
	 */
	 private static Logger log = Logger.getLogger(FenetrePrincipale.class);		
	
	/**
	 * La fenêtre
	 */
	private JFrame fenetre = null;
	
	/**
	 * L'écran
	 */
	private Ecran ecran = null;
	
	/**
	 * Barre de statut indiquant la librairie chargée
	 */
	private BarreStatut barreStatut;
	
	/**
	 * Barre de menu
	 */
	private JMenuBar barreMenus;

	/**
	 * Constructeur à 2 arguments
	 * @param controleur Controleur de l'application
	 * @param application L'application 
	 * @throws ExceptionProgrammeExemple 
	 */
	public FenetrePrincipale(ApplicationControleur controleur,Application application) throws ExceptionProgrammeExemple {
		
		super(controleur);
		
		try {
			
			construitFenetre(application);
			
		} catch (ExceptionProgrammeExemple e) {
			
			throw e;
			
		} catch (Throwable t) {
			
			log.error("Une erreur inattendue est survenue lors de la construction de la fenetre : "+ExceptionProgrammeExemple.getStacktrace(t));
			throw new ExceptionVue(ExceptionProgrammeExemple.TYPE_VUE_EXCEPTION_CONSTRUCTION_FENETRE,"Une erreur inattendue est survenue");
			
		}
	}
	
	/**
	 * Accesseur de la fenêtre
	 * @return La fenêtre
	 */
	public JFrame getFenetre() {
		return fenetre;
	}	
	
	/**
	 * Construit la fenêtre
	 * @param application L'application
	 * @throws ExceptionVue 
	 */
	private void construitFenetre(Application application) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, ExceptionVue {

		fenetre = new JFrame("Programme d'exemple "+application.getVersion());
		
		// Look and feel de l'application
		String lookAndFeel = UIManager.getSystemLookAndFeelClassName();
		UIManager.setLookAndFeel(lookAndFeel);
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		fenetre.setBounds(0,0,screenSize.width, screenSize.height-30);
		
		//fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		fenetre.addWindowListener(new java.awt.event.WindowAdapter() {
			   public void windowClosing(java.awt.event.WindowEvent e) {
				 ferme();
			   }
			});
		
		// création d'une barre de menu
		barreMenus = new JMenuBar();
		barreMenus.setBackground(Color.WHITE);
		fenetre.setJMenuBar(barreMenus);
		MenuApplication menu = application.getMenu();
		menu.initMenus(application);
		construitMenu(menu.getItemsMenus());
		
		// création de la barre de statut
		if(application.getInfoLibrairieP11() != null) {
			barreStatut = new BarreStatut();
			barreStatut.setLibrairie(new String(application.getInfoLibrairieP11().libraryDescription).trim());
	        fenetre.getContentPane().add(barreStatut, java.awt.BorderLayout.SOUTH);
		}

	}
	
	/**
	 * Construit le menu
	 * @param itemsMenus Ensemble des éléments constituant le menu de l'application
	 * @throws ExceptionVue 
	 */
	public void construitMenu(TreeMap<String,JMenuItem> itemsMenus) throws ExceptionVue{
		
		try {
		
			Vector<JMenuItem> menuTraites = new Vector<JMenuItem>();
			Vector<JMenuItem> menuRacines = new Vector<JMenuItem>();
			
			if(itemsMenus != null && itemsMenus.values() != null) {

				for (Iterator<JMenuItem> iterator = itemsMenus.values().iterator(); iterator.hasNext();) {
					
					JMenuItem jMenuItem = (JMenuItem) iterator.next();
					boolean racineAtteinte = false;
					while(!racineAtteinte && !menuTraites.contains(jMenuItem)) {
						
						if(jMenuItem instanceof ItemMenu || jMenuItem instanceof ItemMenuCheckbox) {
							String parentId;
							if(jMenuItem instanceof ItemMenu)
								parentId = ((ItemMenu)jMenuItem).getIdParent();
							else 
								parentId = ((ItemMenuCheckbox)jMenuItem).getIdParent();
							if(parentId != null) {
								
								JMenuItem parent = (JMenuItem)itemsMenus.get(parentId);
							
								if(parent != null) {
									menuTraites.add(jMenuItem);
									if(jMenuItem instanceof ItemMenu)
										((ItemMenu)jMenuItem).setEcouteur(this);
									else
										((ItemMenuCheckbox)jMenuItem).setEcouteur(this);
									parent.add(jMenuItem);
									parent.revalidate();
								}
							} else {
								// on est à la racine
								racineAtteinte = true;
								menuRacines.add(jMenuItem);
							}
						} else if(jMenuItem instanceof Menu) {
							String parentId = ((Menu)jMenuItem).getIdParent();
							if(parentId != null) {
								
								JMenuItem parent = (JMenuItem)itemsMenus.get(parentId);
							
								if(parent != null) {
									menuTraites.add(jMenuItem);
									parent.add(jMenuItem);
									parent.revalidate();
								}
							} else {
								// on est à la racine
								racineAtteinte = true;
								menuRacines.add(jMenuItem);
							}
						}
					}
					
				}

			}
			
			if(barreMenus != null) {
				
				for (Iterator<JMenuItem> iterator = menuRacines.iterator(); iterator.hasNext();) {
					barreMenus.add((JMenuItem)iterator.next());
				}
				
			}
		
		} catch (Throwable t) {
			
			log.error("Une erreur inattendue est survenue lors de la construction du menu : "+ExceptionProgrammeExemple.getStacktrace(t));
			throw new ExceptionVue(ExceptionProgrammeExemple.TYPE_VUE_EXCEPTION_CONSTRUCTION_MENU,"Une erreur inattendue est survenue");
			
		}
	}

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.controleurs.ApplicationVue#close()
	 */
	public void ferme() {
		if(fenetre != null) {
			fenetre.setVisible(false);
			fenetre.dispose();
		}
		log.debug("Sortie du programme");
	}

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.controleurs.ApplicationVue#display()
	 */
	public void affiche() {
		if(fenetre != null)
			fenetre.setVisible(true);
	}
	
	/**
	 * Accesseur
	 * @return La barre de statut
	 */
	public BarreStatut getBarreStatut() {
		return barreStatut;
	}
	
	/**
	 * Masque les éléments de l'écran
	 */
    private void masqueElementsEcran() {
    	EcranUtil.supprimeTousLesComposants((JPanel)fenetre.getContentPane());
    	fenetre.setLayout(null);
        fenetre.getContentPane().add(barreStatut, java.awt.BorderLayout.SOUTH);
    }	
	
	/**
	 * Capture d'évènements
	 */
	public void actionPerformed(ActionEvent e){

		if(e.getSource() instanceof ItemMenu || e.getSource() instanceof ItemMenuCheckbox) {
			
			masqueElementsEcran();
			
			if(e.getSource() != null
					&& e.getSource() instanceof ItemMenu
						&& MenuApplication.OPTIONS_CHARGELIB.equalsIgnoreCase(((ItemMenu)e.getSource()).getId())) {

				// Chargement d'une autre bibliotheque
				JFileChooser fc = new JFileChooser();
				fc.setAcceptAllFileFilterUsed(false);
				fc.setFileFilter(Application.getFiltreLibrairie());
				fc.setDialogTitle("Sélectionnez une librairie");

	            int valeurRetour = fc.showOpenDialog(fenetre);

	            if (valeurRetour == JFileChooser.APPROVE_OPTION) {
	                File fichier = fc.getSelectedFile();
	                if(fichier != null)
						try {
							if(getControlleur() != null && fichier != null)
								getControlleur().declencheChargementLibrairie(fichier.getAbsolutePath());
						} catch (ExceptionControleur e1) {
							
							// En cas d'erreur on notifie l'utilisateur
							JOptionPane.showMessageDialog(fenetre,"Une erreur est survenue lors du chargement de la nouvelle librairie",e1.getTypeException(),JOptionPane.ERROR_MESSAGE);
							
						}
	            }
	            
			} else 	if(e.getSource() != null
					&& e.getSource() instanceof ItemMenuCheckbox
						&& MenuApplication.OPTIONS_DEVERROUILLER_MENU.equalsIgnoreCase(((ItemMenuCheckbox)e.getSource()).getId())) {
				
				if(MenuApplication.isMenuVerrouille()) {
					MenuApplication.setMenuVerrouille(false);
					((ItemMenuCheckbox)e.getSource()).setMnemonic('c');
					getControlleur().deverrouilleMenu();
				}
				else {
					MenuApplication.setMenuVerrouille(true);
					((ItemMenuCheckbox)e.getSource()).setMnemonic('h');
					getControlleur().verrouilleMenu();
				}
				
			} else {
				
				// désactive le menu pour éviter tout lancement d'opération simultanée par l'utilisateur
				if(barreMenus != null)
					barreMenus.setEnabled(false);
				
				// déclenche l'opération associée à l'item de menu cliqué
				if(getControlleur() != null)
					getControlleur().declencheOperationMenu(e.getSource());
				
				// reactive le menu
				if(barreMenus != null)
					barreMenus.setEnabled(true);
			}
			
		} else if(e.getSource() instanceof JButton) {
			
			if(ecran != null && getControlleur() != null) {
				
				Vector<String> problemesSaisie = new Vector<String>();
				
				switch(ecran.getType()) {
				
					case EcranUtil.TYPE_ECRAN_AUTHENTIFICATION_UTILISATEUR:
					case EcranUtil.TYPE_ECRAN_AUTHENTIFICATION_SO:
						problemesSaisie = getControlleur().declencheValidationSaisie((Saisie1PIN)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((Saisie1PIN)ecran);
						}
						break;
					
					case EcranUtil.TYPE_ECRAN_INIT_CODE_PORTEUR:
						problemesSaisie = getControlleur().declencheValidationSaisie((Saisie2PIN)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((Saisie2PIN)ecran);
						}
						break;
					
					case EcranUtil.TYPE_ECRAN_MODIF_CODE_PORTEUR:
						problemesSaisie = getControlleur().declencheValidationSaisie((Saisie3PIN)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((Saisie3PIN)ecran);
						}
						break;
					
					case EcranUtil.TYPE_ECRAN_CREATION_OBJETS:
						problemesSaisie = getControlleur().declencheValidationSaisie((SaisieObjet)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((SaisieObjet)ecran);
						}
						break;

					case EcranUtil.TYPE_ECRAN_MODIFICATION_OBJETS:
						problemesSaisie = getControlleur().declencheValidationSaisie((SaisieObjet)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((SaisieObjet)ecran);
						}
						break;
						
					case EcranUtil.TYPE_ECRAN_RECHERCHE_OBJETS:
						masqueElementsEcran();
						getControlleur().declencheOperationSaisie((SaisieFiltreObjet)ecran);
						break;
					
					case EcranUtil.TYPE_ECRAN_GENERATION_AVEC_SEED:
						problemesSaisie = getControlleur().declencheValidationSaisie((SaisieSeed)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((SaisieSeed)ecran);
						}
						break;
					
					case EcranUtil.TYPE_ECRAN_GENERATION_EMPREINTE_MESSAGE:
						problemesSaisie = getControlleur().declencheValidationSaisie((SaisieMessage)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((SaisieMessage)ecran);
						}
						break;
						
					case EcranUtil.TYPE_ECRAN_GENERATION_EMPREINTE_FICHIER:
						problemesSaisie = getControlleur().declencheValidationSaisie((SaisieFichier)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((SaisieFichier)ecran);
						}
						break;		
						
					case EcranUtil.TYPE_ECRAN_GENERATION_SIGNATURE_MESSAGE:
					case EcranUtil.TYPE_ECRAN_VERIFICATION_SIGNATURE_MESSAGE:
						problemesSaisie = getControlleur().declencheValidationSaisie((SaisieMessageSignature)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((SaisieMessageSignature)ecran);
						}
						break;
				
					case EcranUtil.TYPE_ECRAN_GENERATION_SIGNATURE_FICHIER:
					case EcranUtil.TYPE_ECRAN_VERIFICATION_SIGNATURE_FICHIER:
						problemesSaisie = getControlleur().declencheValidationSaisie((SaisieFichierSignature)ecran);
						if(problemesSaisie == null || problemesSaisie.size() == 0) {
							masqueElementsEcran();
							getControlleur().declencheOperationSaisie((SaisieFichierSignature)ecran);
						}
					break;

				}
				
				// On alerte l'utilisateur de la saisie incorrecte en le notifiant des problèmes de saisie
				if(problemesSaisie != null && problemesSaisie.size() > 0) {
					
					String messageAlerte = new String();
					
					for (Iterator<String> iterator = problemesSaisie.iterator(); iterator.hasNext();)
						messageAlerte += (String) iterator.next() + "\n";
					
					// En cas d'erreur on notifie l'utilisateur
					JOptionPane.showMessageDialog(fenetre,messageAlerte,"Saisie incorrecte",JOptionPane.WARNING_MESSAGE);
					
				}
				
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ApplicationEcouteur#afficheResultat(fr.asip.cps3.exemple.modele.Resultat)
	 */
	public void afficheResultat(Resultat resultat) throws ExceptionVue {

		try {
		
			// Initialisation de l'écran correspondant
			if(resultat instanceof ResultatTripleInfo)
				ecran = new SortieResultatTripleInfo(this);
			else if(resultat instanceof ResultatSignatureMessage)
				ecran = new SortieResultatSignatureMessage(this);
			else if(resultat instanceof ResultatSignatureFichier)
				ecran = new SortieResultatSignatureFichier(this);
			else if(resultat instanceof ResultatEmpreinteMessage)
				ecran = new SortieResultatEmpreinteMessage(this);
			else if(resultat instanceof ResultatEmpreinteFichier)
				ecran = new SortieResultatEmpreinteFichier(this);
			else if(resultat instanceof ResultatDoubleInfo)
				ecran = new SortieResultatDoubleInfo(this);
			else if(resultat instanceof ResultatInfo)
				ecran = new SortieResultatInfo(this);
			else if(resultat instanceof ResultatTriple)
				ecran = new SortieResultatTriple(this);
			else if(resultat instanceof ResultatDouble)
				ecran = new SortieResultatDouble(this);
			else if(resultat instanceof ResultatSpecifiqueInfo)
				ecran = new SortieResultatSpecifiqueInfo(this);
			else if(resultat instanceof ResultatSpecifique)
				ecran = new SortieResultatSpecifique(this);
			else if(resultat instanceof Resultat)
				ecran = new SortieResultat(this);
			
			if(ecran != null) {
			
				// affichage
				ecran.affiche();
				
				//###############//
				//# REMPLISSAGE #//
				//###############//
				
				//# OPERATIONS ET CODES RETOURS #//
				
				// Dans tous les cas
				((Sortie)ecran).setOperation(resultat.getTraitement());
							
				if(resultat.getCodeRetour() == 0 && resultat.getRetour() != null && resultat.getRetour().length() != 0)
					((Sortie)ecran).setRetour(resultat.getRetour());
				else
					((Sortie)ecran).setRetour(resultat.getCodeRetourStr());

	
				// Resultat au moins double
				if(resultat instanceof ResultatDouble 
						|| resultat instanceof ResultatDoubleInfo
							|| resultat instanceof ResultatTriple || resultat instanceof ResultatTripleInfo) {
					
					if(resultat instanceof ResultatDouble 
							|| resultat instanceof ResultatTriple) {
						((SortieResultatDouble)ecran).setOperation2(((ResultatDouble)resultat).getOperation2());
						((SortieResultatDouble)ecran).setCodeRetour2(((ResultatDouble)resultat).getCodeRetour2());					
					} else {
						((SortieResultatDoubleInfo)ecran).setOperation2(((ResultatDoubleInfo)resultat).getOperation2());
						((SortieResultatDoubleInfo)ecran).setCodeRetour2(((ResultatDoubleInfo)resultat).getCodeRetour2());
					}
				}
	
				// Resultat triple
				if(resultat instanceof ResultatTriple || resultat instanceof ResultatTripleInfo) {
					if(resultat instanceof ResultatTriple) {
						((SortieResultatTriple)ecran).setOperation3(((ResultatTriple)resultat).getOperation3());
						((SortieResultatTriple)ecran).setCodeRetour3(((ResultatTriple)resultat).getCodeRetour3());					
					} else {
						((SortieResultatTripleInfo)ecran).setOperation3(((ResultatTripleInfo)resultat).getOperation3());
						((SortieResultatTripleInfo)ecran).setCodeRetour3(((ResultatTripleInfo)resultat).getCodeRetour3());
					}
				}
				
				// Resultat avec empreinte
				if(resultat instanceof ResultatEmpreinteMessage || resultat instanceof ResultatEmpreinteFichier) {
					if(resultat instanceof ResultatEmpreinteMessage)
						((SortieResultatEmpreinteMessage)ecran).setEmpreinte(((ResultatEmpreinteMessage)resultat).getEmpreinte());
					else
						((SortieResultatEmpreinteFichier)ecran).setEmpreinte(((ResultatEmpreinteFichier)resultat).getEmpreinte());
	
				} 
				
				// Resultat avec Signature
				else if(resultat instanceof ResultatSignatureMessage || resultat instanceof ResultatSignatureFichier) {
						if(resultat instanceof ResultatSignatureMessage)
							((SortieResultatSignatureMessage)ecran).setSignature(((ResultatSignatureMessage)resultat).getSignature());
						else
							((SortieResultatSignatureFichier)ecran).setSignature(((ResultatSignatureFichier)resultat).getSignature());
	
					}			
				
				// masquage de la barre de statut de la fenêtre principale
				if(barreStatut != null)
					barreStatut.setVisible(false);
				
				if(ecran instanceof SortieResultatInfo)
					((SortieResultatInfo)ecran).setInfos((ResultatInfo)resultat);
				if(ecran instanceof SortieResultatSpecifiqueInfo)
					((SortieResultatSpecifiqueInfo)ecran).setInfos((ResultatSpecifiqueInfo)resultat);
	
				
				// Actualisation du panel
				if(fenetre != null) {
					fenetre.getContentPane().validate();
					fenetre.getContentPane().repaint();
				}
			}
			
		} catch (Throwable t) {
			
			log.error("Une erreur inattendue est survenue lors de l'affichage du resultat : "+ExceptionProgrammeExemple.getStacktrace(t));
			throw new ExceptionVue(ExceptionProgrammeExemple.TYPE_VUE_EXCEPTION_AFFICHAGE_RESULTAT,"Une erreur inattendue est survenue");
			
		}

	}

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ApplicationEcouteur#afficheEcran(int, java.lang.Object)
	 */
	@SuppressWarnings("unchecked")
	public void afficheEcran(int typeEcran,Object objet) throws ExceptionVue {
	
		try {
		
			// En fonction du type d'écran demander on créé l'écran qui convient
			switch(typeEcran) {
			
				case EcranUtil.TYPE_ECRAN_INIT_CODE_PORTEUR:
					ecran = new Saisie2PIN(this,typeEcran);
				break;
				
				case EcranUtil.TYPE_ECRAN_MODIF_CODE_PORTEUR:
					ecran = new Saisie3PIN(this,typeEcran,"Entrez le code PIN actuel :", "Entrez le nouveau code PIN", "Entrez le nouveau code PIN à nouveau");
				break;
				
				case EcranUtil.TYPE_ECRAN_AUTHENTIFICATION_UTILISATEUR:
					ecran = new Saisie1PIN(this,typeEcran,"Entrez le code PIN :");
				break;
				
				case EcranUtil.TYPE_ECRAN_AUTHENTIFICATION_SO:
					ecran = new Saisie1PIN(this,typeEcran,"Entrez le code PUK :");
				break;
	
				case EcranUtil.TYPE_ECRAN_CREATION_OBJETS:
						ecran = new SaisieObjet(this,typeEcran);
				break;
	
				case EcranUtil.TYPE_ECRAN_MODIFICATION_OBJETS:
					ecran = new SaisieObjet(this,typeEcran,(Objet)objet);
				break;
					
				case EcranUtil.TYPE_ECRAN_RECHERCHE_OBJETS:
					ecran = new SaisieFiltreObjet(this,typeEcran);
				break;
				
				case EcranUtil.TYPE_ECRAN_GENERATION_EMPREINTE_MESSAGE:
					if(objet instanceof Algo)
						ecran = new SaisieMessage(this,typeEcran,(Algo)objet);
				break;
				
				case EcranUtil.TYPE_ECRAN_GENERATION_EMPREINTE_FICHIER:
					if(objet instanceof Algo)
						ecran = new SaisieFichier(this,typeEcran,(Algo)objet);
				break;
	
				case EcranUtil.TYPE_ECRAN_GENERATION_SIGNATURE_MESSAGE:
					if(objet instanceof Vector<?>) {
						Vector<Object> algoCle = (Vector<Object>) objet;
						if(algoCle != null && algoCle.size() == 2 && algoCle.get(0) instanceof Algo && algoCle.get(1) instanceof Cle)
							ecran = new SaisieMessageSignature(this,typeEcran,(Algo)algoCle.get(0),(Cle)algoCle.get(1));
					}
	
				break;
				
				case EcranUtil.TYPE_ECRAN_GENERATION_SIGNATURE_FICHIER:
					if(objet instanceof Vector<?>) {
						Vector<Object> algoCle = (Vector<Object>) objet;
						if(algoCle != null && algoCle.size() == 2 && algoCle.get(0) instanceof Algo && algoCle.get(1) instanceof Cle)
							ecran = new SaisieFichierSignature(this,typeEcran,(Algo)algoCle.get(0),(Cle)algoCle.get(1));
					}
				break;
	
				case EcranUtil.TYPE_ECRAN_VERIFICATION_SIGNATURE_MESSAGE:
					if(objet instanceof Vector<?>) {
						Vector<Object> algoCleMessageSignature = (Vector<Object>) objet;
						if(algoCleMessageSignature != null && algoCleMessageSignature.size() == 4 
								&& algoCleMessageSignature.get(0) instanceof Algo 
									&& algoCleMessageSignature.get(1) instanceof Cle
										&& algoCleMessageSignature.get(2) instanceof char[]
	                                          && algoCleMessageSignature.get(3) instanceof String)
							ecran = new SaisieMessageSignature(this,typeEcran, 
											(Algo)algoCleMessageSignature.get(0),
												(Cle)algoCleMessageSignature.get(1),
													(char[])algoCleMessageSignature.get(2),
														(String)algoCleMessageSignature.get(3));
					}
	
				break;
							
				case EcranUtil.TYPE_ECRAN_VERIFICATION_SIGNATURE_FICHIER:
					if(objet instanceof Vector<?>) {
						Vector<Object> algoCleFichierSignature = (Vector<Object>) objet;
						if(algoCleFichierSignature != null && algoCleFichierSignature.size() == 4 
								&& algoCleFichierSignature.get(0) instanceof Algo 
									&& algoCleFichierSignature.get(1) instanceof Cle
										&& algoCleFichierSignature.get(2) instanceof String
	                                          && algoCleFichierSignature.get(3) instanceof String)
							ecran = new SaisieFichierSignature(this,typeEcran, 
											(Algo)algoCleFichierSignature.get(0),
												(Cle)algoCleFichierSignature.get(1),
													(String)algoCleFichierSignature.get(2),
														(String)algoCleFichierSignature.get(3));
					}
	
				break;
				
				
				case EcranUtil.TYPE_ECRAN_GENERATION_AVEC_SEED:
					ecran = new SaisieSeed(this,typeEcran);
				break;			
			}
			
			if(ecran != null)
				ecran.affiche();
		
		} catch (Throwable t) {
			
			log.error("Une erreur inattendue est survenue lors de l'affichage de l'ecran : "+ExceptionProgrammeExemple.getStacktrace(t));
			throw new ExceptionVue(ExceptionProgrammeExemple.TYPE_VUE_EXCEPTION_AFFICHAGE_ECRAN,"Une erreur inattendue est survenue");
			
		}
		
	}	

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ApplicationEcouteur#afficheEcran(int)
	 */
	public void afficheEcran(int typeEcran) throws ExceptionVue {
		afficheEcran(typeEcran,null);
	}
	
	
	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ApplicationEcouteur#chargementLibrairie(java.lang.String)
	 */
	public void chargementLibrairie(String description) {
		
		if(barreStatut != null) {
			barreStatut.setLibrairie(description);
			JOptionPane.showMessageDialog(fenetre,"La librairie "+description+" a été chargée avec succès");
			barreStatut.setVisible(true);
		}
		
	}

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ApplicationEcouteur#problemeChargementLibrairie(java.lang.Throwable)
	 */
	public void problemeChargementLibrairie(int typeException, Application application) {
		
		switch(typeException) {
		
			case ExceptionProgrammeExemple.TYPE_LIBRAIRIE_EXCEPTION_CHARGEMENT_LIB_P11:
				JOptionPane.showMessageDialog(fenetre,"La librairie spécifiée est inaccessible ou invalide!\nLa librairie précèdente va être rechargée","Erreur librairie PKCS#11",JOptionPane.ERROR_MESSAGE);
				break;
				
			case ExceptionProgrammeExemple.TYPE_LIBRAIRIE_EXCEPTION_CHARGEMENT_LIB_TS:
				JOptionPane.showMessageDialog(fenetre,"Une erreur est survenue au chargement de la librairie des traitements spécifiques.\nLe module Traitements spécifiques est inutilisable.","Erreur librairie native des traitements spécifiques",JOptionPane.ERROR_MESSAGE);
				application.getMenu().setItemMenuNonActif(MenuApplication.TRAITEMENTSSPECIFIQUES);
				break;
				
			default:
				JOptionPane.showMessageDialog(fenetre,"Une erreur inattendue est survenue","Erreur librairie",JOptionPane.ERROR_MESSAGE);				
				break;
		}
		
	}
	
	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ApplicationEcouteur#majMenus(fr.asip.cps3.exemple.modele.Application)
	 */
	public void majMenus(Application application) {
		MenuControleur.majMenus(application);
	}

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#afficheException(java.lang.Exception)
	 */
	public void afficheException(Exception exception) {

		if(exception != null && exception.getMessage() != null
				&& exception instanceof ExceptionProgrammeExemple)
			JOptionPane.showMessageDialog(fenetre,exception.getMessage(),((ExceptionProgrammeExemple)exception).getTypeException(),JOptionPane.ERROR_MESSAGE);
		else {
			JOptionPane.showMessageDialog(fenetre,"Une erreur inconnue est survenue","Erreur",JOptionPane.ERROR_MESSAGE);
		}
		
	}
	
	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#demandeConnexionLecteur()
	 */
	public int demandeConnexionLecteur() {
		
		Object[] options = {"Relancer", "Annuler"};
		int reponse = 0;
		
		reponse = JOptionPane.showOptionDialog(fenetre,
				"Veuillez connecter un lecteur avec une carte supportée et relancer",
				"Authentification Impossible",
			    JOptionPane.YES_NO_OPTION,
			    JOptionPane.ERROR_MESSAGE,
			    null,
			    options,
			    options[0]);
		
		// Transposition vers code ANNULATION 
		if(reponse == 1)
			reponse = -1;
		
		return reponse;
	
	}
	
	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#demandeIntroductionCarte()
	 */
	public int demandeInsertionCarte() {
		
		Object[] options = {"Relancer", "Annuler"};
		
		int reponse = 0;
		
		reponse = JOptionPane.showOptionDialog(fenetre,
				"Veuillez insérer une carte supportée et relancer",
				"Authentification Impossible",
			    JOptionPane.YES_NO_OPTION,
			    JOptionPane.ERROR_MESSAGE,
			    null,
			    options,
			    options[0]);

		// Transposition vers code ANNULATION 
		if(reponse == 1)
			reponse = -1;
		
		return reponse;
	
	}

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#demandeSaisieCodePorteur(long, long)
	 */
	public Object[] demandeSaisieCodePorteur(long nbEssais, long conformiteCodePorteur, String numeroSerieCarte) {
		
		Object[] saisieCode = new Object[2];
		
		SaisieCodeNbEssais dialogSaisieCode = new SaisieCodeNbEssais(fenetre, "Saisie du code porteur de la carte", TraitementsUtil.retranscritFlag(conformiteCodePorteur), numeroSerieCarte, TraitementsUtil.retranscritFlag(nbEssais), TraitementsUtil.retranscritCouleurFlag(nbEssais));
		dialogSaisieCode.affiche();
		
		saisieCode[0] = dialogSaisieCode.getChoixUtilisateur();
		saisieCode[1] = dialogSaisieCode.getCode();
	
		return saisieCode;

	}	

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#demandeRecyclageCodePorteur(long, long)
	 */
	public Object[] demandeRecyclageCodePorteur(long nbEssais, long conformiteCodeDeblocage, long conformiteCodePorteur, String numeroSerieCarte) {
		
		Object[] saisieCodes = new Object[4];
		
		SaisieRecyclage dialogRecyclage = new SaisieRecyclage(fenetre, "Recyclage de la carte", TraitementsUtil.retranscritFlag(conformiteCodeDeblocage), TraitementsUtil.retranscritFlag(conformiteCodePorteur), numeroSerieCarte, TraitementsUtil.retranscritFlag(nbEssais), TraitementsUtil.retranscritCouleurFlag(nbEssais));
		dialogRecyclage.affiche();
		
		saisieCodes[0] = dialogRecyclage.getChoixUtilisateur();
		saisieCodes[1] = dialogRecyclage.getCodeDeblocage();
		saisieCodes[2] = dialogRecyclage.getCodePorteur1();
		saisieCodes[3] = dialogRecyclage.getCodePorteur2();		
		return saisieCodes;

	}	
	
	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#demandeChoixNbEssaisPossiblesAvantBlocageCodePorteur()
	 */
	public int demandeChoixNbEssaisPossiblesAvantBlocageCodePorteur() {

		Object[] options = {"Code à 3 tentatives", "Code à N tentatives", "Annuler"};
		
		int reponse = 0;
		
		reponse = JOptionPane.showOptionDialog(fenetre,
				"Afin de constater la transposition de l'état de saisie\ndu code porteur, vous êtes invité à saisir un code porteur erroné.\nVeuillez choisir une des options suivantes pour ce test :",
				"Etat de saisie du code porteur",
			    JOptionPane.YES_NO_OPTION,
			    JOptionPane.WARNING_MESSAGE,
			    null,
			    options,
			    options[0]);

		// Transposition vers code CHOIX UTILISATEUR (côté C)
		reponse++;
		if(reponse == 3)
			reponse = -1;		
		
		return reponse;		
		
	}

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#demandeDemarrageAttenteEvenementSlot()
	 */
	public int demandeActionLecteurCarte(int typeAction, String numeroSerieCarte) {

		Object[] options = {"Valider", "Annuler"};
		
		int reponse = 0;
		
		String message;
		String titre;	
		
		switch (typeAction) {
		
			case TraitementsUtil.TYPE_ACTION_RETRAIT_CARTE:
			 message = "Retirez une carte d'un lecteur, puis cliquez sur Valider";
			 titre = "Retrait carte";			 
			 break;

			case TraitementsUtil.TYPE_ACTION_INSERTION_CARTE:
			 if(numeroSerieCarte != null)
				 message = "Insérez la carte "+numeroSerieCarte+" dans un des lecteurs, puis Valider";
			 else
				 return 0;
			 titre = "Retrait carte";
			 break;

			case TraitementsUtil.TYPE_ACTION_RETRAIT_LECTEUR:
			 message = "Veuillez débrancher un lecteur contenant une carte, puis cliquez sur Valider";
			 titre = "Retrait lecteur";
			 break;

			case TraitementsUtil.TYPE_ACTION_CONNEXION_LECTEUR:
			 if(numeroSerieCarte != null) {
				 message = "Veuillez rebrancher le lecteur ou réintroduire la carte "+numeroSerieCarte+" dans un autre lecteur connecté, puis cliquez sur Valider";
			 } else
				 return 0;
			 titre = "Retrait lecteur";
			 break;
			 
			 default:
				 return 0;
		
		}
		
		reponse = JOptionPane.showOptionDialog(fenetre,
				message,
				titre,
			    JOptionPane.YES_NO_OPTION,
			    JOptionPane.WARNING_MESSAGE,
			    null,
			    options,
			    options[0]);

		// Transposition vers code ANNULATION 
		if(reponse == 1)
			reponse = -1;		
		
		return reponse;		
		
	}
	
	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#declencheAlerteCarteRetrouvee()
	 */
	public void declencheAlerteCarteRetrouvee() {

		JOptionPane.showMessageDialog(fenetre,"La carte a été retrouvée","Information",JOptionPane.INFORMATION_MESSAGE);
		
	}	

	/*
	 * (non-Javadoc)
	 * @see fr.asip.cps3.exemple.modele.ecouteurs.ApplicationEcouteur#declencheDemandeModificationObjetDonneesApplicatives()
	 */
	public Object[] declencheDemandeModificationObjetDonneesApplicatives(byte[] valeur) {

		Object[] saisieValeur = new Object[2];
		
		SaisieAttributObjet dialogModifObjet = new SaisieAttributObjet(fenetre, "Modification d’un jeton d’établissement", "CPS_DATA");
		dialogModifObjet.setAttribut(TraitementsUtil.getHexadecimal(valeur,16));
		dialogModifObjet.affiche();

		saisieValeur[0] = dialogModifObjet.getChoixUtilisateur();
		saisieValeur[1] = dialogModifObjet.getValeurAttribut();
		
		return saisieValeur;
		
	}
	
}
